using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Markup;
using Rhizome.Contract;

namespace Rhizome.Model
{
#if !SILVERLIGHT && !WINDOWS_PHONE
	[MarkupExtensionReturnType(typeof (IActiveObjectHost))]
#endif
	public sealed partial class ActiveObjectHost : IActiveObjectHost
	{
		private readonly Activator _activator;
		private readonly Dispatcher _dispatcher;
		private readonly Timer _timer;
		private bool _disposed;

		public event EventHandler StepFailed
		{
			[DebuggerStepThrough]
			add { _activator.StepFailed += value; }
			[DebuggerStepThrough]
			remove { _activator.StepFailed -= value; }
		}

		public ActiveObjectHost()
		{
			_dispatcher = new Dispatcher(this);
			_timer = new Timer();
			_activator = new Activator(this);

#if !SILVERLIGHT && !WINDOWS_PHONE
			ThreadPriority = ThreadPriority.Normal;
			ApartmentState = ApartmentState.MTA;
#endif
			SynchronizationContext = new ActiveObjectHostSynchronizationContext(this);
		}

		#region IActiveObjectHost Members

		public void Dispose()
		{
			if (!_disposed)
			{
				_activator.Stop();
				_dispatcher.Clear();
				_timer.Clear();
			}
			_disposed = true;
			GC.SuppressFinalize(this);
		}

		public void Sleep(IActiveObject obj, int timeout)
		{
			_dispatcher.Sleep(obj, timeout);
		}

		public void Add(IActiveObject obj)
		{
			_dispatcher.Add(obj);
		}

		public void Remove(IActiveObject obj)
		{
			_timer.Remove(obj);
			_dispatcher.Remove(obj);
		}

		public void Sleep(IActiveObject obj)
		{
			_dispatcher.Sleep(obj);
		}

		public void WakeUp(IActiveObject obj)
		{
			_dispatcher.WakeUp(obj);
		}

		public SynchronizationContext SynchronizationContext { get; private set; }

		public string ThreadName { get; set; }
		public bool IsBackground { get; set; }

#if SILVERLIGHT || WINDOWS_PHONE // xaml compatibility
        public string ThreadPriority { get; set; }
        public string ApartmentState { get; set; }
#else
		public ThreadPriority ThreadPriority { get; set; }
		public ApartmentState ApartmentState { get; set; }
#endif

		public void Start()
		{
			_activator.Start(ThreadName, IsBackground
#if !SILVERLIGHT && !WINDOWS_PHONE
			                 , ThreadPriority, ApartmentState
#endif
				);
		}

		#endregion
	}

#if !SILVERLIGHT && !WINDOWS_PHONE
	public sealed class ActiveObjectHostExtension : MarkupExtension
	{
		public string ThreadName { get; set; }
		public bool IsBackground { get; set; }
		public ApartmentState ApartmentState { get; set; }
		public ThreadPriority ThreadPriority { get; set; }

		public override object ProvideValue(IServiceProvider serviceProvider)
		{
			return
				new ActiveObjectHost
					{
						ApartmentState = ApartmentState,
						IsBackground = IsBackground,
						ThreadName = ThreadName,
						ThreadPriority = ThreadPriority
					};
		}
	}
#endif
}